<?php
namespace App\Helper;

use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Signer\Key;
use Lcobucci\JWT\Token;
use Lcobucci\JWT\ValidationData;
use Swoft\Redis\Redis;

/**
 * Class JwtHelper
 * @package App\Helper
 */
class JwtHelper
{

    /**
     * 发行人
     * @var
     */
    private $issuer;

    /**
     * 使用地
     * @var
     */
    private $audience;

    /**
     * 有效时常
     * @var
     */
    private $exp;

    /**
     * 签名方法
     * @var
     */
    private $signer;

    /**
     * @return mixed
     */
    public function getSigner()
    {
        return $this->signer;
    }

    /**
     * @return mixed
     */
    public function getKey()
    {
        return $this->key;
    }

    /**
     * 密钥
     * @var
     */
    private $key;

    /**
     * 获取redis key
     * @param $uid
     * @return string
     */
    public function getRedisKey($uid){
        return "token_$uid";
    }

    /**
     * 获取token
     * @param $uid
     * @param int $type
     * @param string $unionId
     * @return array
     */
    public function getToken($uid, $type = 1, $unionId = ''): array {
        $redis_key = $this->getRedisKey($uid);
        // 假设token存在于Redis 直接获取token剩余时间
        if(Redis::ttl($redis_key) <= 2){
            // 已经过期 或者快过期了
            $time = time();
            $token = (new Builder())->issuedBy($this->issuer)
                ->permittedFor($this->audience)
                ->identifiedBy(crc32($time.$uid), true)
                ->issuedAt($time)
                ->expiresAt($time + $this->exp)
                ->withClaim('uid', $uid)
                ->withClaim('type', $type)
                ->withClaim('unionId', $unionId)
                ->getToken($this->signer, new Key($this->key));

            // 生产token成功 写入redis
            Redis::setex($redis_key, (int) $this->exp, (string) $token);
        }

        return [
            'token'=>Redis::get($redis_key),
            'expire_in'=>Redis::ttl($redis_key)
        ];
    }

    /**
     * @param $uid
     * @return bool
     */
    public function delToken($uid): bool {
        $redis_key = $this->getRedisKey($uid);
        return Redis::del($redis_key);
    }

    /**
     * 自动延期
     * @param $uid
     * @param $token
     */
    public function delayExpired($uid, $token){
        $redis_key = $this->getRedisKey($uid);
        Redis::setex($redis_key, (int) $this->exp, (string) $token);
    }

    /**
     * @return mixed
     */
    public function getIssuer()
    {
        return $this->issuer;
    }

    /**
     * @return mixed
     */
    public function getAudience()
    {
        return $this->audience;
    }

    /**
     * @return mixed
     */
    public function getExp()
    {
        return $this->exp;
    }

}
